/*
    作者：zx
    时间：2022.11.25
    描述: 内存管理 位图实现
*/

#include "tools/bitmap.h"
#include "tools/klib.h"
#include "comm/cpu_instr.h"

int bitmap_byte_count(bitmap_t * bitmap)
{
    return (bitmap->bit_count-1)/8 +1;
}

void bitmap_init(bitmap_t * bitmap, uint8_t * bits, int bit_count, int init_bit)
{
    bitmap->bit_count = bit_count;
    bitmap->bits = bits;

    int bitmap_byte = bitmap_byte_count(bitmap);
    kernel_memset(bitmap->bits, init_bit ? 0xFF : 0, bitmap_byte);
}

// 获取index位的值
int bitmap_bit_get(bitmap_t * bitmap, int index)
{
    return ((bitmap->bits[index/8])>>(index % 8)) & 1;
}

// 设置index位开始的count个值
void bitmap_bit_set(bitmap_t * bitmap, int index, int bit, int count)
{
    for(int i = 0; (i<count) && (index<bitmap->bit_count); i++, index++)
    {
        if(bit) 
        {
            bitmap->bits[index/8] |= 1 << (index % 8);
        }
        else
        {
            bitmap->bits[index/8] &= ~(1 << (index % 8));
        }
    }
}

// 判断index位是否空闲未使用
int bitmap_bit_used(bitmap_t * bitmap, int index)
{
    return bitmap_bit_get(bitmap, index) ? 1 : 0;
}

// 查找位图连续count个值为bit(默认0)的地址，并分配
int bitmap_alloc_nbits (bitmap_t * bitmap, int bit, int count) {
    int search_idx = 0;
    int ok_idx = -1;

    while (search_idx < bitmap->bit_count) {
        // 定位到第一个相同的索引处
        if (bitmap_bit_get(bitmap, search_idx) != bit) {
            // 不同，继续寻找起始的bit
            search_idx++;
            continue;
        }

        // 记录起始索引
        ok_idx = search_idx;

        // 继续计算下一部分
        int i;
        for (i = 1; (i < count) && (search_idx < bitmap->bit_count); i++) {
            if (bitmap_bit_get(bitmap, search_idx++) != bit) {
                // 不足count个，退出，重新进行最外层的比较
                ok_idx = -1;
                break;
            }
        }

        // 找到，设置各位，然后退出
        if (i >= count) {
            bitmap_bit_set(bitmap, ok_idx, ~bit, count);
            return ok_idx;
        }
    }
    return -1;
}